package com.chessgame.model;

/**
 * 棋子类，表示棋盘上的一个棋子
 */
public class Piece {
    private PieceType type;
    private int x;
    private int y;

    public Piece(PieceType type, int x, int y) {
        this.type = type;
        this.x = x;
        this.y = y;
    }

    public PieceType getType() {
        return type;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public void setPosition(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public boolean isRed() {
        return type.isRed();
    }

    public String getDisplayName() {
        return type.getDisplayName();
    }

    /**
     * 判断移动是否合法
     * @param board 当前棋盘
     * @param targetX 目标位置X坐标
     * @param targetY 目标位置Y坐标
     * @return 移动是否合法
     */
    public boolean isValidMove(Board board, int targetX, int targetY) {
        // 基本边界检查
        if (targetX < 0 || targetX >= 9 || targetY < 0 || targetY >= 10) {
            return false;
        }

        // 目标位置有己方棋子，不能移动
        Piece targetPiece = board.getPieceAt(targetX, targetY);
        if (targetPiece != null && targetPiece.isRed() == this.isRed()) {
            return false;
        }

        // 根据不同棋子类型判断移动是否合法
        switch (type) {
            case RED_GENERAL:
            case BLACK_GENERAL:
                return isValidGeneralMove(targetX, targetY);
            case RED_ADVISOR:
            case BLACK_ADVISOR:
                return isValidAdvisorMove(targetX, targetY);
            case RED_ELEPHANT:
            case BLACK_ELEPHANT:
                return isValidElephantMove(board, targetX, targetY);
            case RED_HORSE:
            case BLACK_HORSE:
                return isValidHorseMove(board, targetX, targetY);
            case RED_CHARIOT:
            case BLACK_CHARIOT:
                return isValidChariotMove(board, targetX, targetY);
            case RED_CANNON:
            case BLACK_CANNON:
                return isValidCannonMove(board, targetX, targetY);
            case RED_SOLDIER:
            case BLACK_SOLDIER:
                return isValidSoldierMove(targetX, targetY);
            default:
                return false;
        }
    }

    private boolean isValidGeneralMove(int targetX, int targetY) {
        // 将/帅只能在九宫格内移动
        boolean inPalace = isInPalace(targetX, targetY);
        if (!inPalace) {
            return false;
        }

        // 将/帅每次只能移动一格，横向或纵向
        int deltaX = Math.abs(targetX - x);
        int deltaY = Math.abs(targetY - y);
        return (deltaX == 1 && deltaY == 0) || (deltaX == 0 && deltaY == 1);
    }

    private boolean isValidAdvisorMove(int targetX, int targetY) {
        // 仕/士只能在九宫格内移动
        if (!isInPalace(targetX, targetY)) {
            return false;
        }

        // 仕/士只能斜着走一格
        int deltaX = Math.abs(targetX - x);
        int deltaY = Math.abs(targetY - y);
        return deltaX == 1 && deltaY == 1;
    }

    private boolean isValidElephantMove(Board board, int targetX, int targetY) {
        // 相/象不能过河
        
      // if (isRed() && targetY > 4 || !isRed() && targetY < 5) {
        if (board.isRedTurn() && targetY < 5 || !board.isRedTurn() && targetY > 4) {
            return false;
        }

        // 相/象走田字（必须是两格）
        int deltaX = Math.abs(targetX - x);
        int deltaY = Math.abs(targetY - y);
        if (deltaX != 2 || deltaY != 2) {
            return false;
        }

        // 检查象眼是否被塞住（象眼位置是田字的中心点）
        int eyeX = (targetX + x) / 2;
        int eyeY = (targetY + y) / 2;
        return board.getPieceAt(eyeX, eyeY) == null;
    }

    private boolean isValidHorseMove(Board board, int targetX, int targetY) {
        int deltaX = Math.abs(targetX - x);
        int deltaY = Math.abs(targetY - y);
        
        // 马走日字
        if (!((deltaX == 2 && deltaY == 1) || (deltaX == 1 && deltaY == 2))) {
            return false;
        }

        // 检查马腿是否被绊住
        int legX = x;
        int legY = y;
        if (deltaX == 2) {
            legX = x + (targetX - x) / 2;
        } else {
            legY = y + (targetY - y) / 2;
        }
        return board.getPieceAt(legX, legY) == null;
    }

    private boolean isValidChariotMove(Board board, int targetX, int targetY) {
        // 车只能直线移动
        if (targetX != x && targetY != y) {
            return false;
        }

        // 检查路径上是否有其他棋子
        int startX = Math.min(x, targetX);
        int endX = Math.max(x, targetX);
        int startY = Math.min(y, targetY);
        int endY = Math.max(y, targetY);

        if (targetX == x) {
            // 纵向移动
            for (int i = startY + 1; i < endY; i++) {
                if (board.getPieceAt(x, i) != null) {
                    return false;
                }
            }
        } else {
            // 横向移动
            for (int i = startX + 1; i < endX; i++) {
                if (board.getPieceAt(i, y) != null) {
                    return false;
                }
            }
        }
        return true;
    }

    private boolean isValidCannonMove(Board board, int targetX, int targetY) {
        // 炮只能直线移动
        if (targetX != x && targetY != y) {
            return false;
        }

        // 计算路径上的棋子数
        int pieceCount = 0;
        int startX = Math.min(x, targetX);
        int endX = Math.max(x, targetX);
        int startY = Math.min(y, targetY);
        int endY = Math.max(y, targetY);

        if (targetX == x) {
            // 纵向移动
            for (int i = startY + 1; i < endY; i++) {
                if (board.getPieceAt(x, i) != null) {
                    pieceCount++;
                }
            }
        } else {
            // 横向移动
            for (int i = startX + 1; i < endX; i++) {
                if (board.getPieceAt(i, y) != null) {
                    pieceCount++;
                }
            }
        }

        Piece targetPiece = board.getPieceAt(targetX, targetY);
        if (targetPiece == null) {
            // 移动时不能翻山
            return pieceCount == 0;
        } else {
            // 吃子时必须翻山
            return pieceCount == 1;
        }
    }

    private boolean isValidSoldierMove(int targetX, int targetY) {
        int deltaX = Math.abs(targetX - x);
        int deltaY = targetY - y;

        if (isRed()) {
            // 红方兵
            if (y > 4) {
                // 过河前只能向前走
                return deltaX == 0 && deltaY == -1;
            } else {
                // 过河后可以横着走
                return (deltaX == 1 && deltaY == 0) || (deltaX == 0 && deltaY == -1);
            }
        } else {
            // 黑方卒
            if (y < 5) {
                // 过河前只能向前走
                return deltaX == 0 && deltaY == 1;
            } else {
                // 过河后可以横着走
                return (deltaX == 1 && deltaY == 0) || (deltaX == 0 && deltaY == 1);
            }
        }
    }

    private boolean isInPalace(int targetX, int targetY) {
        if (isRed()) {
            // 红方九宫格
            return targetX >= 3 && targetX <= 5 && targetY >= 7 && targetY <= 9;
        } else {
            // 黑方九宫格
            return targetX >= 3 && targetX <= 5 && targetY >= 0 && targetY <= 2;
        }
    }
}